using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Text;
using System.Windows.Forms;
using DevExpress.XtraEditors;
using DevExpress.XtraGrid.Views.Grid;
using DevExpress.XtraGrid.Views.Grid.ViewInfo;
using DevExpress.XtraTab;
using DevExpress.XtraTreeList;
using DevExpress.XtraTreeList.Nodes;
using System.IO;
using FirebirdSql.Data.FirebirdClient;
using Model;

namespace FirebirdTool
{
    public partial class FrmMain : DevExpress.XtraEditors.XtraForm
    {
        public FrmMain()
        {
            InitializeComponent();

            this.btnDB.Click += new EventHandler(btnDB_Click);

            this.btnProject.Click += new EventHandler(btnProject_Click);

            this.xtraTab.CloseButtonClick += new EventHandler(xtraTab_CloseButtonClick);

            this.txtNamespace.TextChanged += new EventHandler(txtNamespace_TextChanged);

            this.Shown += new EventHandler(FrmMain_Shown);

            this.treeList.FocusedNodeChanged += new FocusedNodeChangedEventHandler(treeList_FocusedNodeChanged);
            this.treeList.MouseDown += new MouseEventHandler(treeList_MouseDown);

            this.mnuNewQuery.Click += new EventHandler(mnuNewQuery_Click);
            this.mnuCreateModel.Click += new EventHandler(mnuCreateModel_Click);
            this.mnuNewTable.Click += new EventHandler(mnuNewTable_Click);
            this.mnuOpenTable.Click += new EventHandler(mnuOpenTable_Click);
            this.mnuModify.Click += new EventHandler(mnuModify_Click);
            this.mnuDelete.Click += new EventHandler(mnuDelete_Click);
            this.mnuFilter.Click += new EventHandler(mnuFilter_Click);
            this.mnuRemoveFilter.Click += new EventHandler(mnuRemoveFilter_Click);
            this.mnuRefresh.Click += new EventHandler(mnuRefresh_Click);
        }

        private void FrmMain_Shown(object sender, EventArgs e)
        {
            string appPath = Application.StartupPath;
            if (appPath.EndsWith("\\") == false)
                appPath += "\\";
            appPath += "config.rms";

            if (File.Exists(appPath))
            {
                try
                {
                    string[] arr = File.ReadAllLines(appPath, Encoding.UTF8);
                    this.txtProject.Text = arr[0];
                    this.txtNamespace.Text = arr[1];
                    this.txtDB.Text = arr[2];
                }
                catch { }
            }

            RefreshData();
        }

        #region control
        private void txtNamespace_TextChanged(object sender, EventArgs e)
        {
            Util.Namespace = this.txtNamespace.Text;
            Util.SaveSetting(Application.StartupPath, this.txtProject.Text, this.txtNamespace.Text, this.txtDB.Text);
        }
        #endregion control

        #region xtraTab
        private void xtraTab_CloseButtonClick(object sender, EventArgs e)
        {
            this.xtraTab.TabPages.Remove(this.xtraTab.SelectedTabPage);
        }
        #endregion xtraTab

        #region menu
        private void mnuNewQuery_Click(object sender, EventArgs e)
        {
            CreateTabPage(null, null, TabPageType.SQL);
        }

        private void mnuCreateModel_Click(object sender, EventArgs e)
        {
            CreateTabPage((string)this.treeList.FocusedNode.GetValue("RealName"), (string)this.treeList.FocusedNode.GetValue("Name"), TabPageType.CreateModel);
        }

        private void mnuNewTable_Click(object sender, EventArgs e)
        {
            CreateTabPage("", "", TabPageType.NewTable);
        }

        private void mnuOpenTable_Click(object sender, EventArgs e)
        {
            int dbType = (int)this.treeList.FocusedNode.GetValue("DBType");
            if (dbType == 1)
                CreateTabPage((string)this.treeList.FocusedNode.GetValue("RealName"), (string)this.treeList.FocusedNode.GetValue("Name"), TabPageType.OpenTable);
        }

        private void mnuModify_Click(object sender, EventArgs e)
        {
            int dbType = (int)this.treeList.FocusedNode.GetValue("DBType");
            if (dbType == 1)
                CreateTabPage((string)this.treeList.FocusedNode.GetValue("RealName"), (string)this.treeList.FocusedNode.GetValue("Name"), TabPageType.ModifyTable);
            else
                if (dbType == 4)
                    CreateTabPage((string)this.treeList.FocusedNode.GetValue("RealName"), (string)this.treeList.FocusedNode.GetValue("Name"), TabPageType.StoredProcedure);
        }

        private void mnuDelete_Click(object sender, EventArgs e)
        {
            object objRealName = this.treeList.FocusedNode.GetValue("RealName");
            if (objRealName == null)
                return;
            if (objRealName is DBNull)
                return;

            string realName = (string)objRealName;
            if (realName == "")
                return;

            int dbType = (int)this.treeList.FocusedNode.GetValue("DBType");
            if (dbType == 1)
            {
                if (XtraMessageBox.Show("DROP Table " + (string)this.treeList.FocusedNode.GetValue("Name") + "?", "Confirm", MessageBoxButtons.YesNo, MessageBoxIcon.Question) == DialogResult.Yes)
                    DeleteTable(realName);
            }
            else
                if (dbType == 4)
                {
                    if (XtraMessageBox.Show("DROP Stored Procedure " + (string)this.treeList.FocusedNode.GetValue("Name") + "?", "Confirm", MessageBoxButtons.YesNo, MessageBoxIcon.Question) == DialogResult.Yes)
                        DeleteSP(realName);
                }
        }

        private void mnuFilter_Click(object sender, EventArgs e)
        {
            RefreshData();
        }

        private void mnuRemoveFilter_Click(object sender, EventArgs e)
        {
        }

        private void mnuRefresh_Click(object sender, EventArgs e)
        {
        }
        #endregion menu

        #region button
        private void btnProject_Click(object sender, EventArgs e)
        {
            FolderBrowserDialog fbd = new FolderBrowserDialog();
            if (fbd.ShowDialog() == DialogResult.OK)
                this.txtProject.Text = fbd.SelectedPath;

            if (this.txtProject.Text.EndsWith("\\") == false)
                this.txtProject.Text += "\\";

            Util.ProjectPath = this.txtProject.Text;
            Util.SaveSetting(Application.StartupPath, this.txtProject.Text, this.txtNamespace.Text, this.txtDB.Text);
        }

        private void btnDB_Click(object sender, EventArgs e)
        {
            OpenFileDialog ofd = new OpenFileDialog();
            ofd.Filter = "Firebird file|*.FDB";
            if (ofd.ShowDialog() == DialogResult.OK)
            {
                this.txtDB.Text = ofd.FileName;
                Util.DB = this.txtDB.Text;
                Model.Session.DB = this.txtDB.Text;

                Util.SaveSetting(Application.StartupPath, this.txtProject.Text, this.txtNamespace.Text, this.txtDB.Text);

                RefreshData();
            }
        }
        #endregion button

        #region tree
        private void treeList_MouseDown(object sender, MouseEventArgs e)
        {
            TreeListHitInfo hitInfo = this.treeList.CalcHitInfo(e.Location);
            if (e.Button == MouseButtons.Right)
                if (hitInfo.HitInfoType == HitInfoType.Cell || hitInfo.HitInfoType == HitInfoType.Row)
                    this.treeList.FocusedNode = hitInfo.Node;
        }

        private void treeList_FocusedNodeChanged(object sender, FocusedNodeChangedEventArgs e)
        {
            if (e.Node == null)
                return;

            int dbType = (int)e.Node.GetValue("DBType");
            bool NewQuery = false;
            bool CreateModel = false;
            bool NewTable = false;
            bool OpenTable = false;
            bool Modify = false;
            bool Delete = false;
            bool Filter = false;
            bool RemoveFilter = false;
            bool Refresh = false;

            switch (dbType)
            {
                case 0:
                    //tables
                    NewQuery = true;
                    NewTable = true;
                    Refresh = true;
                    break;
                case 1:
                    //table
                    NewQuery = true;
                    CreateModel = true;
                    NewTable = true;
                    OpenTable = true;
                    Modify = true;
                    Delete = true;
                    Filter = true;
                    RemoveFilter = true;
                    Refresh = true;
                    break;
                case 2:
                    //column
                    NewQuery = true;
                    Delete = true;
                    Refresh = true;
                    break;
                case 3:
                    //stored procedures
                    NewQuery = true;
                    Modify = true;
                    Delete = true;
                    Filter = true;
                    RemoveFilter = true;
                    Refresh = true;
                    break;
                case 4:
                    //stored procedure
                    NewQuery = true;
                    Modify = true;
                    Delete = true;
                    Filter = true;
                    RemoveFilter = true;
                    Refresh = true;
                    break;
            }

            this.mnuNewQuery.Visible = NewQuery;
            this.mnuCreateModel.Visible = CreateModel;
            this.mnuNewTable.Visible = NewTable;
            this.mnuOpenTable.Visible = OpenTable;
            this.mnuModify.Visible = Modify;
            this.mnuDelete.Visible = Delete;
            this.mnuFilter.Visible = Filter;
            this.mnuRemoveFilter.Visible = RemoveFilter;
            this.mnuRefresh.Visible = Refresh;
        }
        #endregion tree

        #region function
        private void RefreshData()
        {
            Util.ProjectPath = this.txtProject.Text;
            Util.Namespace = this.txtNamespace.Text;

            Util.DB = this.txtDB.Text;
            Model.Session.DB = this.txtDB.Text;

            try
            {
                if (File.Exists(Util.DB))
                    this.bds.DataSource = Util.GetDetailDB();
            }
            catch
            {
                XtraMessageBox.Show("Database Error!", "Error", MessageBoxButtons.OK, MessageBoxIcon.Error);
            }
        }

        private void DeleteTable(string tableName)
        {
            string scmd = "";
            string serror = "";
            string generator = null;
            List<string> trigger = new List<string>();

            #region delete trigger_name
            scmd = "select rdb$trigger_name as tgname from RDB$TRIGGERS WHERE rdb$relation_name='" + tableName + "';";
            try
            {
                FbDataReader readerGenerator = Util.ExecReader(scmd);
                while (readerGenerator.Read())
                    trigger.Add(((string)readerGenerator["tgname"]).Trim());
            }
            catch (Exception ex)
            {
                MessageBox.Show(ex.Message, "Error", MessageBoxButtons.OK, MessageBoxIcon.Error);
                return;
            }
            #endregion delete trigger_name
            //-------------------------

            #region delete generator
            scmd = "select rdb$generator_name as grname from rdb$generators WHERE rdb$generator_name='GEN_" + tableName + "_ID';";
            try
            {
                FbDataReader readerGenerator = Util.ExecReader(scmd);
                if (readerGenerator.Read())
                    generator = ((string)readerGenerator["grname"]).Trim();
            }
            catch (Exception ex)
            {
                MessageBox.Show(ex.Message, "Error", MessageBoxButtons.OK, MessageBoxIcon.Error);
                return;
            }
            #endregion delete generator
            //-------------------------

            for (int i = 0; i < trigger.Count; i++)
            {
                scmd = "DROP TRIGGER " + trigger[i] + ";";
                serror = Util.ExecNonQuery(scmd);
                if (serror != null)
                {
                    MessageBox.Show(serror, "Error", MessageBoxButtons.OK, MessageBoxIcon.Error);
                    return;
                }
            }
            //-------------------------

            if (generator != null)
            {
                scmd = "DROP GENERATOR " + generator + ";";
                serror = Util.ExecNonQuery(scmd);
                if (serror != null)
                {
                    MessageBox.Show(serror, "Error", MessageBoxButtons.OK, MessageBoxIcon.Error);
                    return;
                }
            }
            //-------------------------

            scmd = "DROP TABLE " + tableName + ";";
            serror = Util.ExecNonQuery(scmd);
            if (serror != null)
            {
                MessageBox.Show(serror, "Error", MessageBoxButtons.OK, MessageBoxIcon.Error);
                return;
            }
            //-------------------------

            this.bds.DataSource = Util.GetDetailDB();
        }

        private void DeleteSP(string spName)
        {
            string scmd = "DROP PROCEDURE " + spName + ";";
            string serror = Util.ExecNonQuery(scmd);
            if (serror != null)
            {
                MessageBox.Show(serror, "Error", MessageBoxButtons.OK, MessageBoxIcon.Error);
                return;
            }

            this.bds.DataSource = Util.GetDetailDB();
        }

        private void CreateTabPage(string realName, string name, TabPageType tabPageType)
        {
            string tabName = "tab";
            string tabTitle = "";
            switch (tabPageType)
            {
                case TabPageType.SQL:
                    tabName += "SQL" + (++Util.NewSQLIndex).ToString();
                    tabTitle = "SQL" + Util.NewSQLIndex.ToString();
                    break;
                case TabPageType.StoredProcedure:
                    tabName += name;
                    tabTitle = name;
                    break;
                case TabPageType.NewTable:
                    tabName += "Table" + (++Util.NewTableIndex).ToString();
                    tabTitle = "Table" + Util.NewTableIndex.ToString();
                    break;
                case TabPageType.ModifyTable:
                    tabName += "ModifyTable" + name;
                    tabTitle = name;
                    break;
                case TabPageType.OpenTable:
                    tabName += "OpenTable" + name;
                    tabTitle = "[Data] " + name;
                    break;
                case TabPageType.CreateModel:
                    tabName += "CreateModel" + name;
                    tabTitle = "[Model] " + name;
                    break;
            }

            XtraTabPage tab = new XtraTabPage();
            tab.Name = "tab";
            tab.Text = tabTitle;

            switch (tabPageType)
            {
                case TabPageType.NewTable:
                    FbTable fbTableNew = new FbTable("", "", true);
                    fbTableNew.SavedEvent += new FbEventHandler(fbTable_SavedEvent);
                    tab.Controls.Add(fbTableNew);
                    fbTableNew.Dock = DockStyle.Fill;
                    break;
                case TabPageType.ModifyTable:
                    FbTable fbTableMod = new FbTable(name, realName, false);
                    fbTableMod.SavedEvent += new FbEventHandler(fbTable_SavedEvent);
                    tab.Controls.Add(fbTableMod);
                    fbTableMod.Dock = DockStyle.Fill;
                    break;
                case TabPageType.CreateModel:
                    FbCsla fbCsla = new FbCsla(name, realName);
                    fbCsla.SavedEvent += new FbEventHandler(fbCsla_SavedEvent);
                    tab.Controls.Add(fbCsla);
                    fbCsla.Dock = DockStyle.Fill;
                    break;
                case TabPageType.SQL:
                    FbSQL fbSQL = new FbSQL(name, realName, "");
                    tab.Controls.Add(fbSQL);
                    fbSQL.Dock = DockStyle.Fill;
                    break;
                case TabPageType.OpenTable:
                    FbSQL fbData = new FbSQL(name, realName);
                    tab.Controls.Add(fbData);
                    fbData.Dock = DockStyle.Fill;
                    break;
                case TabPageType.StoredProcedure:
                    FbSQL fbSQL_SP = new FbSQL(name, realName, Util.GetSPSourceCode(realName));
                    tab.Controls.Add(fbSQL_SP);
                    fbSQL_SP.Dock = DockStyle.Fill;
                    break;
            }

            this.xtraTab.TabPages.Add(tab);
            this.xtraTab.SelectedTabPage = tab;
        }

        private void fbTable_SavedEvent(object sender, FbEventArgs e)
        {
            this.bds.DataSource = Util.GetDetailDB();
            this.xtraTab.SelectedTabPage.Text = (string)e.objValue2;
        }

        private void fbCsla_SavedEvent(object sender, FbEventArgs e)
        {
            this.bds.DataSource = Util.GetDetailDB();
        }
        #endregion function
    }
}